package com.apes.scm.account.creditLine.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.Arith;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.MapUtil;
import com.apes.scm.account.creditLine.model.CreditLine;
import com.apes.scm.account.creditLine.repository.CreditLineRepository;
import com.apes.scm.account.ledger.model.LedgerEntry;
import com.apes.scm.account.ledger.service.LedgerService;
import com.apes.scm.masterdata.enumeration.model.Enumeration;
import com.apes.scm.masterdata.enumeration.model.EnumerationType;
import com.apes.scm.masterdata.enumeration.repository.EnumerationRepository;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class CreditLineService {
    @Autowired
    CreditLineRepository creditLineRepository;
    @Autowired
    LedgerService ledgerService;
    @Autowired
    CreditLineDao creditLineDao;
    @Autowired
    PartyRoleRepository partyRoleRepository;
    /***
     * 功能： 创建
     * @param request
     * @return
     */
    public CreditLine create(SimpleRequest request){
        CreditLine creditLine = request.getO(CreditLine.class);
        //公司信用额度，平台公司1007没有销售部门改动
        Dept dept = SpringManager.getBean(DeptRepository.class).findAll(
                        JpaDsl.toCriteriaByEq("company.id", creditLine.getCompany().getId(),"valid",1)).stream().findFirst()
                .orElseThrow(() -> new RuntimeException("["+creditLine.getCompany().getId()+"]"+creditLine.getCompany().getName()+",该公司下无有效部门！无法制单！请检查！"));
        creditLine.setDept(dept);
        return creditLineRepository.saveAndFlush(creditLine);
    }

    /***
     * 功能：修改
     * @param request
     * @return
     */
    public CreditLine update(SimpleRequest request){
        CreditLine creditLine = request.getO(CreditLine.class);
        //公司信用额度，平台公司1007没有销售部门改动
        Dept dept = SpringManager.getBean(DeptRepository.class).findAll(
                        JpaDsl.toCriteriaByEq("company.id", creditLine.getCompany().getId(),"valid",1)).stream().findFirst()
                .orElseThrow(() -> new RuntimeException("["+creditLine.getCompany().getId()+"]"+creditLine.getCompany().getName()+",该公司下无有效部门！无法制单！请检查！"));
        creditLine.setDept(dept);
        return creditLineRepository.saveAndFlush(creditLine);
    }

    /***
     * 功能：审核
     * @param request
     * @return
     */
    public CreditLine approve(SimpleRequest request){
        CreditLine creditLine = request.getO(CreditLine.class);
        creditLine.setState("approve");
        creditLine.setApproveDate(new Date());
        creditLine.setApproveId(request.getPerson());
        if (creditLine.getDept() == null) {
           creditLine.setDept(creditLineRepository.findOne(creditLine.getId()).getDept());
        }
        if (creditLine.getIncurred() != 0){
            LedgerEntry ledgerEntry = ledgerService.charge(creditLine.getCompany(), creditLine.getDept(), creditLine.getPartner(), "IM_OWN", "AM_PURCHASE",
                    creditLine.getId(), creditLine.getInnerBusinessType(), new Date(), "credit", creditLine.getIncurred());

            // 重新写入历史额度以及余额
            creditLine.setHistoryLine(ledgerEntry.getLedger().getAmount() - ledgerEntry.getIncurred());
            creditLine.setBalanceLine(ledgerEntry.getLedger().getAmount());
        }
        if (creditLine.getAccountPeriod() != null){
            ledgerService.charge(creditLine.getCompany(), SpringManager.getBean(DeptRepository.class)
                            .findByPartyRoleAndDeptType(creditLine.getCompany().getId(), "000007"), creditLine.getPartner(), "IM_OWN", "AM_PURCHASE",
                    creditLine.getId(), creditLine.getInnerBusinessType(), new Date(), "period", creditLine.getAccountPeriod());
        }
        return creditLineRepository.saveAndFlush(creditLine);
    }

    /***
     * 功能：终止
     * @param request
     * @return
     */
    public void repeal(SimpleRequest request){
        Date now = DateUtil.getDate(DateUtil.SHOW_DATE_FORMAT);
        creditLineRepository.findAll(JpaDsl.toCriteriaByEq("state", "approve", "validDateEnd", now)).forEach(creditLine -> {
            creditLine.setState("repeal");
            ledgerService.charge(creditLine.getCompany(), creditLine.getDept(), creditLine.getPartner(), "IM_OWN", "AM_PURCHASE",
                    creditLine.getId(), creditLine.getInnerBusinessType(), new Date(), "credit", creditLine.getIncurred() * -1);
            creditLineRepository.saveAndFlush(creditLine);
        });

    }

    /***
     * 功能：删除
     * @param request
     * @return
     */
    public String delete(SimpleRequest request){
        CreditLine creditLine = request.getO(CreditLine.class);
        creditLineRepository.delete(creditLine);
        return "删除成功";
    }

    /***
     * 功能： 查询客户的信用额度(前端调用)
     */
    public Map<String, Double> findCreditLine(SimpleRequest request){
        CreditLine creditLine = request.getO(CreditLine.class);
        return findLedgerByType(creditLine.getCompany(),  creditLine.getPartner(),"credit");
    }

    /***
     * 功能： 根据type查询对应的客户账目类型额度
     * type: credit 信用额度 period 账期
     */
    public Map<String, Double> findLedgerByType(PartyRole company, PartyRole partner,String type){
        Map<String, Double> creditLineMap = ledgerService.summary(MapUtil.mapper("company", company,  "partner", partner));
        if( creditLineMap.get(type) == null ) creditLineMap.put(type,0.00);
        return creditLineMap;
    }

    /***
     * 功能： 查询客户的账期(前端调用)
     */
    public Map<String, Double> findAccountPeriod(SimpleRequest request){
        CreditLine creditLine = request.getO(CreditLine.class);
        return findLedgerByType(creditLine.getCompany(),  creditLine.getPartner(),"period");
    }

    /***
     * 功能： 查询部门的公司信用额度和已用额度
     */
    public JSONArray findCompanyCreditLine(SimpleRequest request){
        CreditLine creditLine = request.getO(CreditLine.class);
        JSONObject re = new JSONObject();
        re.put("dept_id",creditLine.getDept().getId());
        return creditLineDao.findAllCreditLine(re);
    }

    /**
     * 前端查询客户信用额度明细
     */
    public Map findCreditLineDetails(SimpleRequest request){
        JSONObject jsonObject = request.getJO().getJSONObject("conditionModel");
        Optional.ofNullable(jsonObject.getJSONObject("company")).orElseThrow(() -> new RuntimeException("请选择公司"));
        Optional.ofNullable(jsonObject.getJSONObject("partner")).orElseThrow(() -> new RuntimeException("请选择客户"));
        String companyId = jsonObject.getJSONObject("company").getString("id");
        String partnerId = jsonObject.getJSONObject("partner").getString("id");
        double historyLine = jsonObject.getDouble("historyLine") == null ? 0 : jsonObject.getDouble("historyLine");
        double thisLine = jsonObject.getDouble("incurred") == null ? 0 : jsonObject.getDouble("incurred");
        Integer accountPeriod = jsonObject.getInteger("accountPeriod") == null ? 0 : jsonObject.getInteger("accountPeriod");
        double useLine = 0;
        double invoiceFreeze = 0;
        double invoiceUnsettled = 0;
        double currentFreeze = 0;
        double surplusQuota = 0;
        Integer surplusDate = 0;
        JSONObject param = new JSONObject();
        param.put("companyId",companyId);
        param.put("partnerId",partnerId);
        param.put("accountPeriod",accountPeriod);
        //根据公司和客户查询已使用额度
        JSONArray creditLineArray = creditLineDao.findCreditLineByCompanyAndPartner(param);
        if (creditLineArray.size() != 0){
            useLine = creditLineArray.getJSONObject(0).getDoubleValue("CURRENT_UNSETTLED");
            invoiceFreeze = creditLineArray.getJSONObject(0).getDoubleValue("INVOICE_FREEZE");
            invoiceUnsettled = creditLineArray.getJSONObject(0).getDoubleValue("INVOICE_UNSETTLED");
            currentFreeze = creditLineArray.getJSONObject(0).getDoubleValue("CURRENT_FREEZE");
            surplusQuota = creditLineArray.getJSONObject(0).getDoubleValue("SURPLUS_QUOTA");
            surplusDate = creditLineArray.getJSONObject(0).getInteger("SURPLUS_DATE");
        }
        return MapUtil.mapper("historyLine",historyLine,"accountPeriod",accountPeriod,"useLine",useLine,"thisLine",thisLine,
                "invoiceFreeze",invoiceFreeze,"invoiceUnsettled",invoiceUnsettled,"currentFreeze",currentFreeze,"surplusQuota",surplusQuota,
                "surplusLine", Arith.round(historyLine-useLine+thisLine,4),"surplusDate",surplusDate);
    }

    @Autowired
    EnumerationRepository enumerationRepository;
    public Page<Enumeration> accountPeriod(SimpleRequest request) {
        Integer key = 0  ;
        try {
            key = Integer.valueOf(request.get("key").toString());
        }catch (Exception e){

        }

        List<Enumeration> enumerations= enumerationRepository.findByTypeOrderByDescription("paymentPeriod");
        if(!"".equals(key) && key != 0){
            Enumeration enumeration = new Enumeration();
            enumeration.setId("1");
            enumeration.setDescription(key.toString());
            enumerations.add(enumeration);
        }
        Pageable pageable=new PageRequest(request.get("page"), request.get("size"));
        Page<Enumeration> enumerationPage =new PageImpl<>(enumerations,pageable,Long.valueOf(request.get("size").toString()));
        return enumerationPage;
    }
}
